﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace SilverMap
{
	#region LayerType
	/// <summary>
	/// An enumeration of layer types.
	/// </summary>
	public enum LayerType
	{
		/// <summary>
		/// Specifies a normal layer, where map items are rendered as specified by their x and y values.
		/// </summary>
		Normal,
		/// <summary>
		/// Specifies a scrolling layer in which the entire layer is scrolled based on the layer scroll value. The layer is repeated as needed.
		/// </summary>
		Scrolling,
	}
	#endregion

	#region MapLayer
	/// <summary>
	/// Represents a layer within the map, containing properties that apply to the layer.
	/// </summary>
	public class MapLayer
	{
		/// <summary>
		/// Gets or sets the index position of the layer.
		/// </summary>
		public int Index { get; set; }

		/// <summary>
		/// Gets or sets the rate of scrolling of the current layer when using parallax scrolling.
		/// </summary>
		public double ScrollRate { get; set; }

		/// <summary>
		/// Gets or sets a value indicating the type of layer to render.
		/// </summary>
		public LayerType LayerType { get; set; }

		/// <summary>
		/// Initializes a new instance of the MapLayer class.
		/// </summary>
		public MapLayer()
		{
			LayerType = LayerType.Normal;
		}
	}
	#endregion

	#region MapLayerCollection
	/// <summary>
	/// Represents a collection MapLayer instances.
	/// </summary>
	public class MapLayerCollection : Dictionary<int, MapLayer>
	{
		/// <summary>
		/// Adds a new layer to the collection, setting its index value and returning the newly added layer.
		/// </summary>
		/// <returns>A newly added MapLayer instance.</returns>
		public MapLayer Add()
		{
			var index = 0;
			if (this.Count > 0)
			{
				index = this.Max(i => i.Key);
				index++;
			}
			var layer = new MapLayer { Index = index };
			this.Add(layer);
			return layer;
		}

		/// <summary>
		/// Adds a new layer to the current collection.
		/// </summary>
		/// <param name="layer">The MapLayer instance to add to the collection.</param>
		public void Add(MapLayer layer)
		{
			this.Add(layer.Index, layer);
		}

		/// <summary>
		/// Loads the current collection from the specified XElement.
		/// </summary>
		/// <param name="layersElement">The XElement containing the layers node.</param>
		public void Load(XElement layersElement)
		{
			if (layersElement == null)
				return;

			if (layersElement.HasElements)
			{
				this.Clear();
				foreach (var layerElement in layersElement.Elements())
				{
					var layer = new MapLayer
					{
						Index = layerElement.GetInt32Value("index"),
						ScrollRate = layerElement.GetDoubleValue("scrollRate")
					};

					var layerType = layerElement.GetStringValue("layerType");
					if (!string.IsNullOrEmpty(layerType))
					{
						layer.LayerType = (LayerType)Enum.Parse(typeof(LayerType), layerType, true);
					}
					this.Add(layer);
				}
			}
		}

		/// <summary>
		/// Saves the current collection as nodes of the specified XElement.
		/// </summary>
		/// <param name="layersElement">The XML node in which to add the individual layer nodes.</param>
		/// <exception cref="System.ArgumentNullException"/>
		public void Save(XElement layersElement)
		{
			foreach (var item in this.Values)
			{
				var layerElement = new XElement("layer");
				layersElement.Add(layerElement);

				layerElement.Add(new XAttribute("index", item.Index));
				layerElement.Add(new XAttribute("scrollRate", item.ScrollRate));
				layerElement.Add(new XAttribute("layerType", item.LayerType.ToString()));
			}
		}
	}
	#endregion
}
